package com.temp.interval;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 时间间隔SQL构建
 * @author liubq
 */
public class IntervalBuilder {
    //时间列
    private String timeColumn;
    //数字列
    private String numColumn;
    //单位
    private DateField df = DateField.DAY_OF_YEAR;
    //时间间隔
    private List<Integer> intervals = new ArrayList<>(6);
    //时间点
    private Date point = new Date();
    //正向 true，反向 false
    private boolean forward = false;
    //需要边界外
    private boolean needLastSql = true;
    //结果
    private List<String> sqlList = new ArrayList<>();

    /**
     * 需要边界外
     *
     * @param need
     * @return
     */
    public IntervalBuilder needLast(Boolean need) {
        this.needLastSql = need;
        return this;
    }

    /**
     * 方向
     *
     * @param forard
     * @return
     */
    public IntervalBuilder setForward(Boolean forard) {
        this.forward = forard;
        return this;
    }

    /**
     * 时间点
     *
     * @param point
     * @return
     */
    public IntervalBuilder setPoint(Date point) {
        this.point = point;
        return this;
    }

    /**
     * 时间列
     *
     * @param timeColumn
     * @return
     */
    public IntervalBuilder setTimeColumn(String timeColumn) {
        this.timeColumn = timeColumn;
        return this;
    }

    /**
     * 数字列
     *
     * @param numColumn
     * @return
     */
    public IntervalBuilder setNumColumn(String numColumn) {
        this.numColumn = numColumn;
        return this;
    }

    /**
     * 单位
     *
     * @param df
     * @return
     */
    public IntervalBuilder setDf(DateField df) {
        this.df = df;
        return this;
    }

    /**
     * 时间间隔(都是以起点为标准的)
     *
     * @param intervals
     * @return
     */
    public IntervalBuilder setIntervals(Integer... intervals) {
        if (intervals != null && intervals.length > 0) {
            this.intervals.addAll(Arrays.asList(intervals));
        }
        return this;
    }

    /**
     * 小时的时间范围
     *
     * @return
     */
    public IntervalBuilder action() {
        sqlList.clear();
        if (this.forward) {
            actionTrue();
        } else {
            actionFalse();
        }
//        System.out.println("******************************************");
//        for (String s : sqlList) {
//            System.out.println(s);
//        }
//        System.out.println("******************************************");
        return  this;
    }


    /**
     * 正向小时的时间范围
     *
     * @return
     */
    private void actionTrue() {
        sqlList.clear();
        Date end;
        Date begin = point;
        for (int i = 0; i < intervals.size(); i++) {
            end = DateUtil.offset(point, df, intervals.get(i));
            //添加SQL
            addSql(i, begin, end);
            if (needLastSql && i == intervals.size() - 1) {
                //边界SQL
                addEnd(end);
            }
            begin = end;
        }
    }

    /**
     * 反向小时的时间范围
     *
     * @return
     */
    private void actionFalse() {
        sqlList.clear();
        Date end = point;
        Date begin;
        for (int i = 0; i < intervals.size(); i++) {
            begin = DateUtil.offset(point, df, -1 * intervals.get(i));
            //添加SQL
            addSql(i, begin, end);
            if (needLastSql && i == intervals.size() - 1) {
                //边界SQL
                addEnd(begin);
            }
            end = begin;
        }
    }

    /**
     * 添加SQL
     *
     * @param i
     * @param begin
     * @param end
     */
    private void addSql(int i, Date begin, Date end) {
        //清空
        StringBuilder sql = new StringBuilder();
        sql.append("sum( case when ");
        sql.append("convert(datetime,'").append(DateUtil.formatDateTime(begin)).append("')");
        if (forward) {
            sql.append(" <= ").append(timeColumn).append(" and ").append(timeColumn).append(" < ");
        } else {
            sql.append(" < ").append(timeColumn).append(" and ").append(timeColumn).append(" <= ");
        }
        sql.append("convert(datetime,'").append(DateUtil.formatDateTime(end)).append("')");
        sql.append(" then ").append(numColumn).append(" else 0 end ) AS count").append(i + 1).append("Value");
        sqlList.add(sql.toString());
    }

    /**
     * 添加边界SQL
     *
     * @param end
     */
    private void addEnd(Date end) {
        StringBuilder sql = new StringBuilder();
        sql.setLength(0);
        sql.append("sum( case when ");
        if (forward) {
            sql.append(timeColumn).append(" >= ");
        } else {
            sql.append(timeColumn).append(" < ");
        }
        sql.append("convert(datetime,'").append(DateUtil.formatDateTime(end)).append("')");
        sql.append(" then ").append(numColumn).append(" else 0 end ) AS countLastValue");
        sqlList.add(sql.toString());
    }


    /**
     * 取得结果
     *
     * @return
     */
    public List<String> getSqlList() {
        return sqlList;
    }
}
